﻿package com.hibernate.session;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class MainDriver3 {

	private SessionFactory sessionFactory = null;
	private Session session;
	private Transaction transaction;

	@Before
	public void init() {

		Configuration configuration = new Configuration().configure("session.cfg.xml");
		ServiceRegistry registry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
				.buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(registry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}

	/**
	 * 这个方法执行完之后，数据库中的Author会变成Oracle；
	 * 原因：在Transaction的commit方法中，先调用Session的flush方法，再提交事务，
	 * 1.fush方法可能会发送sql语句（当内存中的对象和数据库中的不一致的时候），但是不会提交事务；
	 * 2.也可以显示的调用flush方法；
	 * 3.注意：在未提交事务或显示的调用session.flush方法之前，也有可能进行flush()操作；
	 * 		1> 执行HQL或QBC查询，会先进行flush操作，以得到数据表的最新的记录；
	 * 		2> 若记录的ID是由数据库底层使用自增的方式生成的，则在调用save()方法后，就会立即发送Insert
	 * 		   因为save方法之后，必须保证ID是存在的，但是在commit方法之前，并不会插入到数据库中；
	 */
	@Test
	public void testSessionOpFlush(){
		News news1 = (News) session.get(News.class, 1);
		news1.setAuthor("Oracle");
	}
	
	/**
	 * refresh()：会强制发送select语句，以使session缓存中对象的状态和数据库中的对象状态一样；
	 * 然而，就算调用了refresh方法，结果也不一定和数据库中的一致，这是由于MySQL数据库隔离级别的问题！！！
	 */
	@Test
	public void testSessionOpRefresh(){
		News news1 = (News) session.get(News.class, 1);
		System.out.println(news1);
		/**
		 * 下面这一句前面打上断点，执行到这里的时候，去手动改掉数据库中的内如：
		 * 1》没有调用refresh方法：则整个方法只会产生一条select语句，下面的打印会直接打印出来；
		 * 2》调用了refresh方法：会再产生一条select语句，
		 */
		session.refresh(news1);
		System.out.println(news1);
	}
	
	/**
	 * clear():会清空session中的对象，再次查询的时候会发送select语句
	 */
	@Test
	public void testSessionOpClear(){
		News news1 = (News) session.get(News.class, 1);
		System.out.println(news1);
		session.clear();
		News news2 = (News) session.get(News.class, 1);
		System.out.println(news2);
	}
	
	
	/**
	 * 下面的两个查询会只产生一条sql语句
	 */
	@Test
	public void testSessionCache(){
		News news1 = (News) session.get(News.class, 1);
		System.out.println(news1);
		News news2 = (News) session.get(News.class, 1);
		System.out.println(news2);
	}
	
	@After
	public void destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
}
